let utils = require('./utils');
/**
 * 真实DOM节点：Element 
 * 
 *   1. 标签类型 h1 div
 *   2. 属性 className id 
 *   3. 子元素 可能是一个数组
 */
class Element {
    //标签名(挂载的节点容器) 属性对象 子元素数组
    constructor(tagName, attrs, children) {
        this.tagName = tagName;
        this.attrs = attrs;
        this.children = children || [];
    }

    //创建真实DOM：把一个虚拟的DOM节点渲染成一个真实的DOM节点
    render() {
        //1、创建一个真实的DOM节点
        let element = document.createElement(this.tagName);
        //2、给此真实的DOM元素节点增加属性
        for (let attr in this.attrs) {
            // element.setAttribute(attr, this.attrs[attr]);  //需要做一些兼容性分析处理
            utils.setAttr(element, attr, this.attrs[attr]);
        }

        //3、挂载(amount)添加子节点 ——> 先序深度遍历：DFS 
        // 优先逐层到底(最左的长子)找儿子的儿子child，然后回溯child(长子管理兄弟们)，由底向上找child的兄弟节点。
        this.children.forEach(child => { 
            //如果子节点是一个元素的话，就调用它的render方法创建子节点的真实DOM，如果是一个字符串的话，创建一个文本节点就可以了
            let childElement = (child instanceof Element) ? child.render() : document.createTextNode(child);
            element.appendChild(childElement);
        });
        return element;
    }
}

/**
 * 创建真实DOM节点
 * 
 * @param {String} tagName  标签名(挂载的节点容器)
 * @param {Object} attrs    属性对象
 * @param {Array} children  子元素数组
 * @returns Element
 */
function createElement(tagName, attrs, children) {
    return new Element(tagName, attrs, children);
}
module.exports = { createElement }; 
module.exports = function(tagName, attrs, children) {
    return new Element(tagName, attrs, children);
}
